home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / cisco / tuecho.c < prev    next >
C/C++ Source or Header  |  1992-08-07  |  10KB  |  352 lines

  1. /*
  2.  * Send / receive TCP or UDP echos in any of a number of bizzare ways.
  3.  *
  4.  *   Joel P. Bion, March 1990
  5.  *   Copyright (c) 1990 cisco Systems. All rights reserved.
  6.  *
  7.  * This "tuecho" program is distributed in the hope that it will be useful,
  8.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10.  *
  11.  * Prompts as:
  12.  *   Host: -- host to send echos to -- can be name or a.b.c.d --
  13.  *   Enter protocol (0 = UDP, 1 = TCP) [0]: -- UDP or TCP
  14.  *   Size of data portion (bytes) [100]: -- bytes in data, excluding headers --
  15.  *   Number of bursts [5]: -- number of bursts of packets to send --
  16.  *   Packets per burst [1]: -- packets per burst, all sent AT ONCE --
  17.  *   Timeout (seconds) [2]:  -- how long to wait for data
  18.  *   Pause interval (seconds) [0]: -- Pause interval between bursts of frames
  19.  *   Type of pattern (specify = 0, increment = 1) [1]: 
  20.  *        -- if 0 specified, allow you to specify a 16bit pattern as four
  21.  *        -- hex digits (see below). If 1, will create a "incrementing",
  22.  *        -- cycling pattern from 0x0000 -> 0xffff ->.
  23.  *   Enter pattern (hex value) [abcd]:    -- if "0" specified above
  24.  */
  25. #include <signal.h>
  26. #include <sys/types.h>
  27. #include <sys/time.h>
  28. #include <sys/socket.h>
  29. #include <netinet/in.h>
  30. #include <netdb.h>
  31. #include <stdio.h>
  32. #include <arpa/inet.h>
  33.  
  34. extern void printf(), fflush(), exit(), bzero(), perror(), strcpy(),
  35.         setbuf(), sscanf(), bcopy(), close(), fprintf();
  36. extern int write(), read(), select(), atoi(), socket(), connect();
  37.  
  38. /* Maximum packet size (integer) */
  39. #define MAXBUF (2000)
  40. #define MAXBYTES (MAXBUF * 4)
  41.  
  42. /* Special patterns... */
  43. #define SPECIAL_NONE (0)
  44. #define SPECIAL_COUNTER (SPECIAL_NONE + 1)
  45. #define SPECIAL_MAX (SPECIAL_COUNTER)
  46.  
  47. /* Protocols */
  48. #define PROTO_UDP (0)
  49. #define PROTO_TCP (PROTO_UDP + 1)
  50. #define PROTO_MAX (PROTO_TCP)
  51.  
  52. /* Global, because interrupt routine references them */
  53. int
  54.     lost,            /* Packets whose echos are not received */
  55.     good,            /* We received a good reply */
  56.     corrupted,            /* We received a bad reply */
  57.     sentout,            /* How many we sent out */
  58.     outc;            /* How many chars out */
  59.  
  60.  
  61. /* Guarantee CRs at random times */
  62. void cprint(c)
  63.     char c;
  64. {
  65.     printf("%c", c);
  66.     if (++outc == 70) {
  67.     printf("\n");
  68.     outc = 0;
  69.     }
  70.     fflush(stdout);
  71. }
  72.  
  73. void cprintcr()
  74. {
  75.     if (outc != 0)
  76.       printf("\n");
  77. }
  78.  
  79. unsigned getint(prompt, defa, fc)
  80.     char *prompt;
  81.     unsigned defa;
  82.     char fc;
  83. {
  84.     char s[1000];
  85.     unsigned u;
  86.  
  87.     if (fc == 'x')
  88.       printf("%s [%x]: ", prompt, defa);
  89.     else
  90.       printf("%s [%d]: ", prompt, defa);
  91.     fgets(s, 999, stdin);
  92.     if ((s[0] == '\0') || (s[0] == '\n'))
  93.       return(defa);
  94.     else {
  95.     if (fc == 'x')
  96.       sscanf(s,"%x", &u);
  97.     else
  98.       sscanf(s,"%d", &u);
  99.     return(u);
  100.     }
  101. }
  102.  
  103.  
  104.  
  105. void outhere()
  106. {
  107.     cprintcr();
  108.     printf("\nAt end, sent out = %d, good = %d, lost = %d, corrupted = %d.\n",
  109.        sentout, good, lost, corrupted);
  110. }
  111.  
  112. void outhere_exit()
  113. {
  114.     outhere();
  115.     exit(0);
  116. }
  117.  
  118. void usage_exit()
  119. {
  120.     printf("usage: tuecho\n");
  121.     printf("  with no parameters will prompt you for information, or another form:\n");
  122.     printf("\n tuecho host proto size nbursts ppburst timeout pauseint ptype\n");
  123.     printf("        [pattern] (on same command line as above)\n");
  124.     printf("\n");
  125.     printf(" Where:\n");
  126.     printf("     host: host to receive your echos. (can be name or a.b.c.d form)\n");
  127.     printf("    proto: 0 for UDP, 1 for TCP\n");
  128.     printf("     size: size of echo packet, excluding headers\n");
  129.     printf("  nbursts: total number of \"bursts\" of echo packets to send\n");
  130.     printf("  ppburst: how many echo packets should be in each burst\n");
  131.     printf("  timeout: how many seconds to wait for the reply (allow more time for bursts)\n");
  132.     printf(" pauseint: Pause interval, in seconds, between bursts\n");
  133.     printf("    ptype: 0 to allow you to specify a hex pattern as the final \"pattern\" parameter\n");
  134.     printf("           1 for \"increasing cyclic\" 16-bit pattern going from 0x0000 to 0xffff\n");
  135.     printf("         and back again, until each echo packet is filled\n");
  136.     printf("  pattern: four character hex pattern (no leading 0x), if ptype = 1, to insert repeatedly\n");
  137.     printf("           in the echo packets\n");
  138.     exit(0);
  139. }
  140.  
  141. void sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
  142.            pause_int)
  143.     int sock;            /* Socket to send / receive from */
  144.     int ptype;            /* Pattern type (normal, or a special) */
  145.     int pattern;        /* Pattern (if normal) */
  146.     int bufsize;        /* Buffer size to send */
  147.     int bursts;            /* Number of bursts */
  148.     int burstsize;        /* Size of bursts */
  149.     struct timeval timeout;    /* Timeout */
  150.     int pause_int;        /* Pause interval */
  151. {
  152.     int i, j, k, ok, readin;
  153.     int nb;
  154.     unsigned int bufo[MAXBUF];    /* Packet to send out */
  155.     unsigned int bufi[MAXBUF];    /* Packet to accept */
  156.     fd_set readmask;        /* For "select" call */
  157.  
  158.     /* Set up select mask */
  159.     FD_ZERO(&readmask);
  160.     FD_SET(sock, &readmask);
  161.     /* Set up the pattern. Check for specials... */
  162.     switch (ptype) {
  163.       case SPECIAL_COUNTER:
  164.     for (i = 0; i < (bufsize / 4); i++)
  165.       bufo[i] = i;
  166.     break;
  167.       case SPECIAL_NONE:
  168.       default:
  169.     for (i = 0; i < (bufsize / 4); i++)
  170.       bufo[i] = pattern;
  171.     break;
  172.     }
  173.     for (i = 0; (i < bursts); i++)    {
  174.     if (pause_int)
  175.       sleep(pause_int);
  176.     if (ptype == SPECIAL_COUNTER)
  177.       bufo[0] = i;
  178.     for (j = 0; j < burstsize; j++) {
  179.         if (write(sock, (char *) bufo, bufsize) < 0) {
  180.         perror("writing on datagram socket.");
  181.         outhere();
  182.         exit(1);
  183.         }
  184.         sentout++;
  185.     }
  186.     for (j = 0; j < burstsize; j++) {
  187.         nb = select(FD_SETSIZE, &readmask, (fd_set *) 0,
  188.             (fd_set *) 0, &timeout);
  189.         if (nb <= 0) {
  190.         lost++;
  191.         cprint('.');
  192.         FD_SET(sock, &readmask);
  193.         continue;
  194.         }
  195.         if (FD_ISSET(sock, &readmask)) {
  196.         bzero((char *) bufi, bufsize);
  197.         if ((readin = read(sock, (char *) bufi, bufsize)) < 0) {
  198.             perror("Reading on datagram socket.");
  199.             outhere();
  200.             exit(1);
  201.         } else {
  202.             ok = 1;
  203.             for (k = 0; ((k < (bufsize / 4)) && (ok)); k++)
  204.               ok = (bufo[k] == bufi[k]);
  205.             if (!(ok)) {
  206.             corrupted++;
  207.             cprint('*');
  208.             continue;
  209.             } else {
  210.             good++;
  211.             cprint('!');
  212.             continue;
  213.             }
  214.         }
  215.         }
  216.     }
  217.     }
  218.     outhere();
  219. }
  220.  
  221. void printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
  222.            proto, pause_int)
  223.     int ptype;            /* Pattern type (normal, or a special) */
  224.     int pattern;        /* Pattern (if normal) */
  225.     int bufsize;        /* Buffer size to send */
  226.     int bursts;            /* Number of bursts */
  227.     int burstsize;        /* Size of bursts */
  228.     struct timeval timeout;    /* Timeout */
  229.     struct sockaddr_in server;    /* Remote server IP address */
  230.     int proto;            /* Protocol */
  231.     int pause_int;
  232.  
  233. {
  234.     printf("\nSending %d bursts of %d %s packets, data portions being %d bytes,\n",
  235.        bursts, burstsize, ((proto == PROTO_TCP) ? ("TCP") : ("UDP")),
  236.        bufsize);
  237.     printf("with a timeout of %d seconds,\nthe pattern being ",
  238.        timeout.tv_sec);
  239.     switch (ptype) {
  240.       case SPECIAL_COUNTER:
  241.     printf("an incrementing value in the packet");
  242.     break;
  243.       case SPECIAL_NONE:
  244.       default:
  245.     printf("0x%x in each four bytes", pattern);
  246.     break;
  247.     }
  248.     printf("\n");
  249.     printf("Pause interval: %d seconds\n", pause_int);
  250.     printf("Sending to IP address %u.%u.%u.%u...\n",
  251.        (unsigned) server.sin_addr.S_un.S_un_b.s_b1,
  252.        (unsigned) server.sin_addr.S_un.S_un_b.s_b2,
  253.        (unsigned)server.sin_addr.S_un.S_un_b.s_b3,
  254.        (unsigned) server.sin_addr.S_un.S_un_b.s_b4);
  255. }
  256.  
  257. void askinfo(argc, argv, hostname, proto,
  258.          bufsize, bursts, burstsize, timeout, ptype, pattern, pause_int)
  259.     int argc;
  260.     char **argv, *hostname;
  261.     int *proto, *bufsize, *bursts, *burstsize;
  262.     struct timeval *timeout;
  263.     int *ptype;
  264.     unsigned *pattern;
  265.     int *pause_int;
  266. {
  267.     if ((argc > 9) || ((argc == 2) && (argv[1][0] == '-') &&
  268.                (argv[1][1] == 'h')))
  269.       usage_exit();
  270.  
  271.     if (argc > 1)
  272.       strcpy(hostname, argv[1]);
  273.     else {
  274.     printf("Host: ");
  275.     gets(hostname);
  276.     }
  277.     *proto = ((argc > 2) ? (atoi(argv[2])) :
  278.           (int) getint("Enter protocol (0 = UDP, 1 = TCP)", 0, 'd'));
  279.     *bufsize = ((argc > 3) ? (atoi(argv[3])) :
  280.         (int) getint("Size of data portion (bytes)", 100, 'd'));
  281.     *bursts = ((argc > 4) ? (atoi(argv[4])) :
  282.            (int) getint("Number of bursts", 5, 'd'));
  283.     *burstsize = ((argc > 5) ? (atoi(argv[5])) :
  284.           (int) getint("Packets per burst", 1, 'd'));
  285.     timeout->tv_sec = ((argc > 6) ? (atoi(argv[6])) :
  286.                (int) getint("Timeout (seconds)", 2, 'd'));
  287.     *pause_int = ((argc > 7) ? (atoi(argv[7])) :
  288.           (int) getint("Enter pause interval", 0, 'd'));
  289.     *ptype = ((argc > 8) ? (atoi(argv[8])) :
  290.           (int) getint("Type of pattern (specify = 0, increment = 1)",
  291.                1, 'd'));
  292.     if (*ptype == SPECIAL_NONE)
  293.       if (argc > 9)
  294.     sscanf(argv[9], "%x", pattern);
  295.       else
  296.     *pattern = getint("Enter pattern (hex value)", 0xabcd, 'x');
  297. }
  298.  
  299. void init()
  300. {
  301.     setbuf(stdout, NULL);
  302.     good = sentout = corrupted = lost = outc = 0;
  303. }
  304.  
  305. void main(argc, argv)
  306.     int argc;
  307.     char **argv;
  308. {
  309.     char hostname[1000];
  310.     int bufsize, bursts, proto, ptype, burstsize, sock;
  311.     struct hostent *hp, *gethostbyname();
  312.     struct in_addr ip;
  313.     struct sockaddr_in server;
  314.     struct timeval timeout;
  315.     unsigned int pattern, pause_int;
  316.  
  317.     askinfo(argc, argv, hostname, &proto, &bufsize, &bursts, &burstsize,
  318.         &timeout, &ptype, &pattern, &pause_int);
  319.     signal(SIGINT, outhere_exit);
  320.     ip.s_addr = inet_addr(hostname);
  321.     if (ip.s_addr == -1) {
  322.     hp = gethostbyname(hostname);
  323.     if (hp == NULL) {
  324.         fprintf(stderr, "%s: %s: unknown host\n", argv[0],
  325.             argv[1]);
  326.         exit(1);
  327.     }
  328.     bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  329.     } else
  330.       bcopy(&ip, &server.sin_addr, sizeof(ip));
  331.     printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
  332.           proto, pause_int);
  333.     sock = socket(AF_INET, SOCK_DGRAM, 0);
  334.     if (sock < 0) {
  335.     perror("Opening stream socket.");
  336.     exit(1);
  337.     }
  338.     server.sin_family = AF_INET;
  339.     server.sin_port = htons(((struct servent *)
  340.                  getservbyname("echo",((proto == PROTO_UDP) ?
  341.                            ("udp") : ("tcp")
  342.                            )))->s_port);
  343.     if (connect(sock, &server, sizeof(server)) < 0) {
  344.     perror("connecting stream socket");
  345.     exit(1);
  346.     }
  347.     sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
  348.           pause_int);
  349.     close(sock);
  350.     exit(0);
  351. }
  352.